package com.medical.app.service.impl;

import com.medical.app.entity.HealthRecord;
import com.medical.app.repository.HealthRecordRepository;
import com.medical.app.service.HealthRecordService;
import com.medical.app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@Service
public class HealthRecordServiceImpl implements HealthRecordService {

    @Autowired
    private HealthRecordRepository healthRecordRepository;

    @Autowired
    private UserService userService;

    @Override
    public HealthRecord saveOrUpdateHealthRecord(HealthRecord healthRecord) {
        // 检查是否已存在相同日期的记录
        Optional<HealthRecord> existingRecord = healthRecordRepository
                .findByUserIdAndRecordDate(healthRecord.getUser().getId(), healthRecord.getRecordDate());

        if (existingRecord.isPresent()) {
            // 更新现有记录
            HealthRecord recordToUpdate = existingRecord.get();
            updateRecordFields(recordToUpdate, healthRecord);
            return healthRecordRepository.save(recordToUpdate);
        } else {
            // 创建新记录
            return healthRecordRepository.save(healthRecord);
        }
    }

    @Override
    public HealthRecord updateHeightWeight(Long userId, Double height, Double weight, LocalDate recordDate) {
        Optional<HealthRecord> existingRecord = healthRecordRepository.findByUserIdAndRecordDate(userId, recordDate);
        HealthRecord healthRecord;

        if (existingRecord.isPresent()) {
            healthRecord = existingRecord.get();
            healthRecord.setHeight(height);
            healthRecord.setWeight(weight);
            // 重新计算BMI
            if (height != null && weight != null && height > 0) {
                double heightInMeter = height / 100.0;
                healthRecord.setBmi(weight / (heightInMeter * heightInMeter));
            }
        } else {
            healthRecord = new HealthRecord();
            healthRecord.setUser(userService.findById(userId).orElseThrow(() -> new RuntimeException("用户不存在")));
            healthRecord.setRecordDate(recordDate);
            healthRecord.setHeight(height);
            healthRecord.setWeight(weight);
            // 自动计算BMI
            if (height != null && weight != null && height > 0) {
                double heightInMeter = height / 100.0;
                healthRecord.setBmi(weight / (heightInMeter * heightInMeter));
            }
        }

        return healthRecordRepository.save(healthRecord);
    }

    @Override
    public HealthRecord updateSteps(Long userId, Integer steps, LocalDate recordDate) {
        Optional<HealthRecord> existingRecord = healthRecordRepository.findByUserIdAndRecordDate(userId, recordDate);
        HealthRecord healthRecord;

        if (existingRecord.isPresent()) {
            healthRecord = existingRecord.get();
            healthRecord.setSteps(steps);
        } else {
            healthRecord = new HealthRecord();
            healthRecord.setUser(userService.findById(userId).orElseThrow(() -> new RuntimeException("用户不存在")));
            healthRecord.setRecordDate(recordDate);
            healthRecord.setSteps(steps);
        }

        return healthRecordRepository.save(healthRecord);
    }

    @Override
    public HealthRecord updateSleepHours(Long userId, Double sleepHours, LocalDate recordDate) {
        Optional<HealthRecord> existingRecord = healthRecordRepository.findByUserIdAndRecordDate(userId, recordDate);
        HealthRecord healthRecord;

        if (existingRecord.isPresent()) {
            healthRecord = existingRecord.get();
            healthRecord.setSleepHours(sleepHours);
        } else {
            healthRecord = new HealthRecord();
            healthRecord.setUser(userService.findById(userId).orElseThrow(() -> new RuntimeException("用户不存在")));
            healthRecord.setRecordDate(recordDate);
            healthRecord.setSleepHours(sleepHours);
        }

        return healthRecordRepository.save(healthRecord);
    }

    // 其他方法保持不变...
    @Override
    public List<HealthRecord> getUserHealthRecords(Long userId) {
        return healthRecordRepository.findByUserIdOrderByRecordDateDesc(userId);
    }

    @Override
    public Optional<HealthRecord> getHealthRecordByDate(Long userId, LocalDate recordDate) {
        return healthRecordRepository.findByUserIdAndRecordDate(userId, recordDate);
    }

    @Override
    public Optional<HealthRecord> getLatestHealthRecord(Long userId) {
        return healthRecordRepository.findLatestByUserId(userId);
    }

    @Override
    public List<HealthRecord> getHealthRecordsByDateRange(Long userId, LocalDate startDate, LocalDate endDate) {
        return healthRecordRepository.findByUserIdAndRecordDateBetween(userId, startDate, endDate);
    }

    @Override
    public void deleteHealthRecord(Long id) {
        healthRecordRepository.deleteById(id);
    }

    @Override
    public Optional<HealthRecord> findById(Long id) {
        return healthRecordRepository.findById(id);
    }

    @Override
    public long getHealthRecordCount(Long userId) {
        return healthRecordRepository.countByUserId(userId);
    }

    @Override
    public List<HealthRecord> getRecentHealthRecords(Long userId, int days) {
        LocalDate startDate = LocalDate.now().minusDays(days - 1);
        return healthRecordRepository.findRecentRecords(userId, startDate);
    }

    // 辅助方法：更新记录字段
    private void updateRecordFields(HealthRecord target, HealthRecord source) {
        if (source.getHeight() != null) {
            target.setHeight(source.getHeight());
        }
        if (source.getWeight() != null) {
            target.setWeight(source.getWeight());
        }
        if (source.getSteps() != null) {
            target.setSteps(source.getSteps());
        }
        if (source.getSleepHours() != null) {
            target.setSleepHours(source.getSleepHours());
        }
        // 如果身高或体重有更新，重新计算BMI
        if ((source.getHeight() != null || source.getWeight() != null) &&
                target.getHeight() != null && target.getWeight() != null && target.getHeight() > 0) {
            double heightInMeter = target.getHeight() / 100.0;
            target.setBmi(target.getWeight() / (heightInMeter * heightInMeter));
        }
    }
}